package cn.com.pagoda.ideplugin.service.pwdGen.service;


import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 密码请求体
 * @author Mch
 * @date 2023-05-27
 */
public class PwdReq {

    /**
     * 总数, 默认为8位
     */
    private int total = 8;

    /**
     * 需求密码类型
     * 如果value=0||null, 皆认为是随机数量
     */
    private Map<String, Integer> generators;


    public void checkData() {
        if (generators.isEmpty()) {
            throw new RuntimeException("必须指明需求密码类型");
        }
    }

    /**
     * 调整数量
     * 1、 如果数量恰好够，则无需调整
     * 2、 否则，增加未指定类型的数量
     */
    public void resetRemainNum() {
        // 值为null的换为0
        generators.replaceAll((k, v) -> Optional.ofNullable(v).orElse(0));
        // 已经设置了值的
        int sum = generators.values().stream().mapToInt(Integer::intValue).sum();
        if (sum == total) {
            return;
        }
        int count = (int) generators.values().stream().filter(v -> v == 0).count();
        // 事先给每个0的类型预留1
        AtomicInteger remain = new AtomicInteger(total - sum - count);
        if (remain.get() < 0) {
            throw new RuntimeException("每个类型之和不得大于总数量");
        }

        // 随机分配未指定数量的密码类型
        Random random = new Random();
        AtomicInteger times = new AtomicInteger();
        generators.forEach((k, v) -> {
            if (v == 0) {
                times.getAndIncrement();
                if (remain.get() == 0) {
                    // 分配1
                    generators.put(k, 1);
                } else {
                    // 假如就剩最后一个了，就直接把剩余量都给他
                    if (times.get() == count) {
                        generators.put(k, remain.get() + 1);
                        return;
                    }
                    int ran = random.nextInt(remain.get());
                    // 加上分配的1
                    generators.put(k, ran + 1);
                    remain.addAndGet(-ran);
                }
            }

        });
    }

    public int getTotal() {
        return total;
    }

    public void setTotal(int total) {
        this.total = total;
    }

    public Map<String, Integer> getGenerators() {
        return generators;
    }

    public void setGenerators(Map<String, Integer> generators) {
        this.generators = generators;
    }
}
